package io.renren.modules.generator.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import io.renren.common.utils.Constant;
import io.renren.common.utils.R;
import io.renren.common.utils.RedisKeys;
import io.renren.common.utils.RedisService;
import io.renren.common.vo.ProductExportVo;
import io.renren.modules.generator.dao.ProductDao;
import io.renren.modules.generator.entity.*;
import io.renren.modules.generator.service.*;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


@Service("productService")
public class ProductServiceImpl extends ServiceImpl<ProductDao, ProductEntity> implements ProductService {

    @Autowired
    private ProductDao productDao;

    @Autowired
    private AddressProductService addressProductService;

    @Autowired
    private RedisService redisService;

    @Autowired
    private DictionaryService dictionaryService;


    @Autowired
    private CustomerService customerService;

    @Autowired
    private AddressService addressService;


    @Override
    public List<ProductEntity> queryPage(Map<String, Object> params) {
        List<ProductEntity> list =productDao.queryPage(params);

        return list;
    }

    @Override
    public int queryPageTotal(Map<String, Object> params) {
        return productDao.queryPageTotal(params);
    }

    @Override
    public ProductEntity queryEntityById(int id) {

        return productDao.queryEntityById(id);
    }

    @Override
    public void save(ProductEntity product) {
        computeMeasurementUnitNumber(product);
        product.setVolume(product.getCaseHeight()*product.getCaseLength()*product.getCaseWidth());
        this.insert(product);
        List<AddressProductEntity> addressProducts = product.getAddressProducts();
        if(addressProducts != null && addressProducts.size() > 0){
            saveAddressProduct(product.getAddressProducts(),product.getId());
        }

    }

    @Override
    public void update(ProductEntity product) {
        computeMeasurementUnitNumber(product);
        product.setVolume(product.getCaseHeight()*product.getCaseLength()*product.getCaseWidth());
        this.updateById(product);
        HashMap<String, Object> map = new HashMap<>();
        map.put("product_id",product.getId());
        addressProductService.deleteByMap(map);
        saveAddressProduct(product.getAddressProducts(),product.getId());

    }

    @Override
    public List<AddressProductEntity> queryProductAddressByProductId(int id) {
        return productDao.queryProductAddressByProductId(id);
    }

    @Override
    public List<ProductEntity> queryByCustomerIdAndFromAddressId(Integer customerId, Integer fromAddressId) {

        return productDao.queryByCustomerIdAndFromAddressId(customerId,fromAddressId);
    }

    @Override
    public ProductEntity queryByNumber(String productNumber) {
       return this.selectOne(new EntityWrapper<ProductEntity>()
                .eq(StringUtils.isNotBlank(productNumber),"product_number",productNumber));
    }

    @Override
    @Transactional
    public R importFile(Workbook book){

        Pattern compile = Pattern.compile("^[0-9]+([.]{1}[0-9]+){0,1}$");

        Sheet sheet = book.getSheetAt(0);

        List<ProductEntity> productEntities = new ArrayList<>();


        Map<String, List<AddressEntity>>  customerAddressMap = new HashMap<>();


        for (int i = 1; i <= sheet.getLastRowNum(); i++) {
            Row row = sheet.getRow(i);

            ProductEntity productEntity = new ProductEntity();

            if(row.getCell(0) != null && !row.getCell(0).toString().trim().equals("")){
                row.getCell(0).setCellType(Cell.CELL_TYPE_STRING);
                String productNumber =  row.getCell(0).getStringCellValue().trim();
                if(productNumber.equals("end")){
                    break;
                }

                productEntity.setProductNumber(productNumber);

            }else{
                return R.error("第"+i+"行产品编码不能为空");
            }

            if(row.getCell(1) != null && !row.getCell(1).toString().trim().equals("")){
                row.getCell(1).setCellType(Cell.CELL_TYPE_STRING);
                String productCnNumber =  row.getCell(1).getStringCellValue().trim();

                productEntity.setProductCnName(productCnNumber);

            }else{
                return R.error("第"+i+"行产品中文名称不能为空");
            }


            /**
             * 英文名称
              */
            if(row.getCell(2) != null && !row.getCell(2).toString().trim().equals("")){
                row.getCell(2).setCellType(Cell.CELL_TYPE_STRING);
                String productEnNumber =  row.getCell(2).getStringCellValue().trim();

                productEntity.setProductEnName(productEnNumber);

            }

            /**
             * 是否lto
             */
            if(row.getCell(3) != null && !row.getCell(3).toString().trim().equals("")){
                row.getCell(3).setCellType(Cell.CELL_TYPE_STRING);
                String lto =  row.getCell(3).getStringCellValue().trim();

                productEntity.setLto(lto);

            }

            /**
             * 温区
              */
            if(row.getCell(4) != null && !row.getCell(4).toString().trim().equals("")){
                row.getCell(4).setCellType(Cell.CELL_TYPE_STRING);
                String temperatureRange =  row.getCell(4).getStringCellValue().trim();
                String temperatureRangKey = RedisKeys.getTemperatureRangKey(temperatureRange);
                Object o = redisService.get(temperatureRangKey);
                DictionaryEntity dictionaryEntity = null;
                if(o != null){
                    dictionaryEntity = (DictionaryEntity) o;
                }else{
                    dictionaryEntity = dictionaryService.queryEntityByCode(temperatureRange);
                    if(dictionaryEntity != null){
                        redisService.set(temperatureRangKey,dictionaryEntity, Constant.getRedisKeyExpireTimeMinutesToSecond(10));
                    }else{
                        return R.error("第"+i+"行温区没有维护在字典里，请先维护");
                    }
                }
                productEntity.setTemperatureRangeDictionaryId(dictionaryEntity.getId());

            }else{
                return R.error("第"+i+"行温区不能为空");
            }


            /**
             * 净重
             */
            if(row.getCell(5) != null && !row.getCell(5).toString().trim().equals("")){
                row.getCell(5).setCellType(Cell.CELL_TYPE_STRING);
                String value =  row.getCell(5).getStringCellValue().trim();
                BigDecimal one = new BigDecimal(value);
                String netWeight = one.toPlainString();
                Matcher matcher = compile.matcher(netWeight);
                if(matcher.matches()){
                    productEntity.setNetWeight(Double.valueOf(netWeight));
                }else{
                    return R.error("第"+i+"行净重请输入数字类型");
                }


            }else{
                return R.error("第"+i+"行净重不能为空");
            }


            /**
             * 毛重grossWeight
             */

            if(row.getCell(6) != null && !row.getCell(6).toString().trim().equals("")){
                row.getCell(6).setCellType(Cell.CELL_TYPE_STRING);
                String value =  row.getCell(6).getStringCellValue().trim();
                BigDecimal one = new BigDecimal(value);
                String grossWeight = one.toPlainString();
                Matcher matcher = compile.matcher(grossWeight);
                if(matcher.matches()){
                    productEntity.setGrossWeight(Double.valueOf(grossWeight));
                }else{
                    return R.error("第"+i+"行毛重请输入数字类型");
                }


            }else{
                return R.error("第"+i+"行毛重不能为空");
            }


            /**
             * 重量单位
             */
            if(row.getCell(7) != null && !row.getCell(7).toString().trim().equals("")){
                row.getCell(7).setCellType(Cell.CELL_TYPE_STRING);
                String weightUom =  row.getCell(7).getStringCellValue().trim();
                productEntity.setWeightUom(weightUom);
            }


            /**
             * 长
             */
            if(row.getCell(8) != null && !row.getCell(8).toString().trim().equals("")){
                row.getCell(8).setCellType(Cell.CELL_TYPE_STRING);
                String value =  row.getCell(8).getStringCellValue().trim();
                BigDecimal one = new BigDecimal(value);
                String length = one.toPlainString();
                Matcher matcher = compile.matcher(length);
                if(matcher.matches()){
                    productEntity.setCaseLength(Double.valueOf(length));
                }else{
                    return R.error("第"+i+"行长请输入数字类型");
                }


            }else{
                return R.error("第"+i+"行长不能为空");
            }

            /**
             * 宽
             */
            if(row.getCell(9) != null && !row.getCell(9).toString().trim().equals("")){
                row.getCell(9).setCellType(Cell.CELL_TYPE_STRING);
                String value =  row.getCell(9).getStringCellValue().trim();
                BigDecimal one = new BigDecimal(value);
                String width = one.toPlainString();
                Matcher matcher = compile.matcher(width);
                if(matcher.matches()){
                    productEntity.setCaseWidth(Double.valueOf(width));
                }else{
                    return R.error("第"+i+"行宽请输入数字类型");
                }


            }else{
                return R.error("第"+i+"行宽不能为空");
            }

            /**
             * 高
             */
            if(row.getCell(10) != null && !row.getCell(10).toString().trim().equals("")){


                row.getCell(10).setCellType(Cell.CELL_TYPE_STRING);
                String value = row.getCell(10).getStringCellValue();
                BigDecimal one = new BigDecimal(value);
                String height = one.toPlainString();
                 Matcher matcher = compile.matcher(height);
               if(matcher.matches()){
                    productEntity.setCaseHeight(Double.valueOf(height));
                }else {
                   return R.error("第" + i + "行高请输入数字类型");
               }


            }else{
                return R.error("第"+i+"行高不能为空");
            }



            /**
             * 长度单位
             */
            if(row.getCell(11) != null && !row.getCell(11).toString().trim().equals("")){
                row.getCell(11).setCellType(Cell.CELL_TYPE_STRING);
                String uom =  row.getCell(11).getStringCellValue().trim();
                productEntity.setDimensionUom(uom);
            }

            /**
             * 默认单位Id
             */

            if(row.getCell(13) != null && !row.getCell(13).toString().trim().equals("")){
                row.getCell(13).setCellType(Cell.CELL_TYPE_STRING);
                String defaultMeasurementUnitDictionaryId =  row.getCell(13).getStringCellValue().trim();

                productEntity.setDefaultMeasurementUnitDictionaryId(Integer.valueOf(defaultMeasurementUnitDictionaryId));

            }else{
                return R.error("第"+i+"行产品默认单位不能为空");
            }

            /**
             * 运输单位
             */
            if(row.getCell(15) != null && !row.getCell(15).toString().trim().equals("")){
                row.getCell(15).setCellType(Cell.CELL_TYPE_STRING);
                String measurementUnitDictionaryId =  row.getCell(15).getStringCellValue().trim();

                productEntity.setMeasurementUnitDictionaryId(Integer.valueOf(measurementUnitDictionaryId));

            }else{
                return R.error("第"+i+"行产品运输单位不能为空");
            }


            /**
             * 换算关系  1个运输单位 =measurementUnitNumber个默认单位i
             */

            if(row.getCell(16) != null && !row.getCell(16).toString().trim().equals("")){
                row.getCell(16).setCellType(Cell.CELL_TYPE_STRING);
                String defaultMeasurementUnitNumber =  row.getCell(16).getStringCellValue().trim();
                Matcher matcher = compile.matcher(defaultMeasurementUnitNumber);
                if(matcher.matches()){
                    Integer integer = Integer.valueOf(defaultMeasurementUnitNumber);

                    productEntity.setDefaultMeasurementUnitNumber(integer);
                }else{
                    return R.error("第"+i+"行产品换算关系请输入数字");
                }
            }else{
                return R.error("第"+i+"行产品换算关系不能为空");
            }

            String customerCode=null;
            /**
             * 客户
             */
            if(row.getCell(17) != null && !row.getCell(17).toString().trim().equals("")){
                row.getCell(17).setCellType(Cell.CELL_TYPE_STRING);
                customerCode =  row.getCell(17).getStringCellValue().trim();
                String customerCodeKey = RedisKeys.getCustomerKey(customerCode);
                Object o = redisService.get(customerCodeKey);
                CustomerEntity customerEntity = null;
                if(o != null){
                    customerEntity = (CustomerEntity) o;
                }else{
                    customerEntity = customerService.queryEntityByCode(customerCode);
                    if(customerEntity != null){
                        redisService.set(customerCodeKey,customerEntity, Constant.getRedisKeyExpireTimeHoursToSecond(2));
                    }else{
                        return R.error("第"+i+"行客户没有维护，请先维护");
                    }
                }
                productEntity.setCustomerId(customerEntity.getId());
                productEntity.setCustomerCode(customerCode);

            }else{
                return R.error("第"+i+"行客户不能为空");
            }


            /**
             * 货品性质字典Id
             */
            if(row.getCell(20) != null && !row.getCell(20).toString().trim().equals("")){
                row.getCell(20).setCellType(Cell.CELL_TYPE_STRING);
                String nature =  row.getCell(20).getStringCellValue().trim();

                productEntity.setProductNatureDictionaryId(Integer.valueOf(nature));

            }

            /**
             * 货品分类字典Id
             */
            if(row.getCell(22) != null && !row.getCell(22).toString().trim().equals("")){
                row.getCell(22).setCellType(Cell.CELL_TYPE_STRING);
                String type =  row.getCell(22).getStringCellValue().trim();

                productEntity.setProductTypeDictionaryId(Integer.valueOf(type));

            }
            /**
             * 单价
             */
            if(row.getCell(23) != null && !row.getCell(23).toString().trim().equals("")){
                row.getCell(23).setCellType(Cell.CELL_TYPE_STRING);
                String price =  row.getCell(23).getStringCellValue().trim();
                boolean matches = compile.matcher(price).matches();
                if(matches){
                    productEntity.setPrice(Double.valueOf(price));
                }else{
                    return R.error("第"+i+"行单价请输入数字类型");
                }


            }

            /**
             * 货值
             */
            if(row.getCell(24) != null && !row.getCell(24).toString().trim().equals("")){
                row.getCell(24).setCellType(Cell.CELL_TYPE_STRING);
                String value =  row.getCell(24).getStringCellValue().trim();
                productEntity.setProductValue(value);

            }

            /**
             * 备注
             */
            if(row.getCell(25) != null && !row.getCell(25).toString().trim().equals("")){
                row.getCell(25).setCellType(Cell.CELL_TYPE_STRING);
                String value =  row.getCell(25).getStringCellValue().trim();
                productEntity.setRemark(value);

            }

            /**
             * 预留字段1
             */
            if(row.getCell(26) != null && !row.getCell(26).toString().trim().equals("")){
                row.getCell(26).setCellType(Cell.CELL_TYPE_STRING);
                String value =  row.getCell(26).getStringCellValue().trim();
                productEntity.setExtendFirst(value);

            }

            /**
             * 预留字段2
             */
            if(row.getCell(27) != null && !row.getCell(27).toString().trim().equals("")){
                row.getCell(27).setCellType(Cell.CELL_TYPE_STRING);
                String value =  row.getCell(27).getStringCellValue().trim();
                productEntity.setExtendSecond(value);

            }



            productEntity.setVolume(productEntity.getCaseHeight()*productEntity.getCaseLength()*productEntity.getCaseWidth());

            productEntities.add(productEntity);
        }

        String productNumber = "";
        String fromAddressCode="";
        String toAddressCode="";
        try{
            if(productEntities.size() > 0){

                for (ProductEntity productEntity: productEntities) {
                    productNumber = productEntity.getProductNumber();
                    this.insert(productEntity);

                    /**
                     * 查询客户下面的地址，校验这个产品维护的地址关系是否存在此客户下
                     */
                    String customerAddresskey = RedisKeys.getCustomerAddresskey(productEntity.getCustomerCode());
                    Object o = redisService.get(customerAddresskey);

                    if(o != null){
                        customerAddressMap = (Map<String, List<AddressEntity>>) o;
                    }else{
                        customerAddressMap= addressService.queryAddressByCustomerIdAndByAddressProperty(productEntity.getCustomerId());
                        redisService.set(customerAddresskey,customerAddressMap,Constant.getRedisKeyExpireTimeMinutesToSecond(10));
                    }

                    try{
                        if(customerAddressMap != null && customerAddressMap.size() > 0){
                            List<AddressEntity> fromAddressEntities =
                                    customerAddressMap.get(Constant.AddressProperty.FROM_ADDRESS.getProperty());

                            List<AddressEntity> toAddressEntities = customerAddressMap.get(Constant.AddressProperty.TO_ADDRESS.getProperty());


                            if(fromAddressEntities != null && fromAddressEntities.size() > 0 && toAddressEntities != null && toAddressEntities.size() > 0){
                                for (int j = 0; j < fromAddressEntities.size(); j++) {
                                    for (int k = 0; k < toAddressEntities.size(); k++) {
                                        AddressEntity toAddressEntity = toAddressEntities.get(k);

                                        AddressEntity fromAddressEntity = fromAddressEntities.get(j);

                                        fromAddressCode =fromAddressEntity.getCode();
                                        toAddressCode = toAddressEntity.getCode();

                                        AddressProductEntity addressProductEntity = new AddressProductEntity();
                                        addressProductEntity.setProductId(productEntity.getId());
                                        addressProductEntity.setToAddressId(toAddressEntity.getId());
                                        addressProductEntity.setFromAddressId(fromAddressEntity.getId());


                                        addressProductService.insert(addressProductEntity);

                                    }
                                }
                            }
                        }
                    }catch (DuplicateKeyException d){
                        d.printStackTrace();
                        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                        throw new DuplicateKeyException("产品码[ "+productNumber+" ]，地址关系["+fromAddressCode+"-->"+toAddressCode+"]维护重复,请在系统中删除,再导入");
                    }catch (Exception e){
                        e.printStackTrace();
                        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    }





                }
            }
        }catch (DuplicateKeyException d){
            d.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            throw new DuplicateKeyException("产品码[ "+productNumber+" ]已经存在,请不要重复导入");
        }catch (Exception e){
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }


        return R.ok();
    }

    @Override
    public ProductEntity queryEntityByProductNumberAndCustomerIdAndAddressId(Map<String, Object> params) {
        return productDao.queryEntityByProductNumberAndCustomerIdAndAddressId(params);
    }

    @Override
    public List<ProductExportVo> queryDataForExcel(Map<String, Object> params) {
        return productDao.queryDataForExcel(params);
    }

    @Override
    public int queryTotalForExcel(Map<String, Object> params) {
        return productDao.queryTotalForExcel(params);
    }

    private void saveAddressProduct(List<AddressProductEntity> addressProductEntities,int productId){
        for (AddressProductEntity addressProductEntity: addressProductEntities
             ) {
            if(addressProductEntity.getFromAddressId() == null || addressProductEntity.getToAddressId() == null){
                continue;
            }
            addressProductEntity.setProductId(productId);
            addressProductService.insert(addressProductEntity);
        }
    }


    private void computeMeasurementUnitNumber(ProductEntity productEntity){
        double defaultMeasurementUnitNumber = productEntity.getDefaultMeasurementUnitNumber();
        double measurementUnitNumber = productEntity.getMeasurementUnitNumber().doubleValue();
        if(measurementUnitNumber != 1 && defaultMeasurementUnitNumber != 0){
            productEntity.setMeasurementUnitNumber(1d);
            productEntity.setDefaultMeasurementUnitNumber(defaultMeasurementUnitNumber/measurementUnitNumber);
        }
    }


}
